package biolean;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.datatransfer.DataFlavor;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.awt.event.WindowListener;
import java.io.File;

import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JToolBar;
import javax.swing.JToolTip;

import javax.swing.JTabbedPane;
import javax.swing.filechooser.FileNameExtensionFilter;

import biolean.AppCanvas.MAdapter;
import biolean.commands.CmdRegister;
import biolean.commands.Filter;
import biolean.commands.SubstractCmd;
import biolean.files.AnnotationFile;
import biolean.files.FileRegister;
import biolean.files.SequenceFile;


public class Biolean extends JFrame implements Commons, DropTargetListener {

	public static CmdRegister cmdRegister = new CmdRegister();
	public static FileRegister fileRegister = new FileRegister();
	public static ScrollingTextArea textArea = new ScrollingTextArea();
	private AppCanvas canvas;
	private CommandsListCanvas commandsCanvas;
	private FileListCanvas fileCanvas;
	private File mLastCurrentFolder = null;
	private boolean mProjectOpened = false;
	private final Biolean biolean = this;
	public Biolean() {
		
		//this.addFocusListener(this);


		cmdRegister.register("Vysek", SubstractCmd.class);
		cmdRegister.register("Filter", Filter.class);

		fileRegister.register(SequenceFile.class, new String[] { "fa", "seq" },"sequence");
		fileRegister.register(AnnotationFile.class, new String[] { "gff" },"annotation");

		setTitle(APP_NAME);
		setSize(APP_WIDTH, APP_HEIGHT);

		setLayout(new BorderLayout(20, 0));
		setLocationRelativeTo(null);
		setVisible(true);
		setResizable(false);
		setDefaultCloseOperation(EXIT_ON_CLOSE);

		JMenuBar menuBar = new JMenuBar();

		JMenu menu = new JMenu("Project");

		JMenuItem newMenuItem = new JMenuItem("New project");
		newMenuItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				saveProject("Create new project",true);
			}
		});

		JMenuItem loadMenuItem = new JMenuItem("Load project");
		loadMenuItem.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				JFileChooser fileChooser = new JFileChooser();
				fileChooser.setFileFilter(new FileNameExtensionFilter(
						"XML file", "xml"));
				if (mLastCurrentFolder != null) {
					fileChooser.setCurrentDirectory(mLastCurrentFolder);
				}
				if (fileChooser.showOpenDialog(canvas) == JFileChooser.APPROVE_OPTION) {
					canvas.project.clear();
					canvas.project.LoadFromXML(fileChooser.getSelectedFile().getAbsolutePath());
					mProjectOpened = true;
					mLastCurrentFolder = fileChooser.getCurrentDirectory();
					canvas.repaint();
				}
			}
		});

		JMenuItem newFileMenuItem = new JMenuItem("Load file");
		newFileMenuItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				JFileChooser fileChooser = new JFileChooser();
				/*fileChooser.setFileFilter(new FileNameExtensionFilter(
						"XML file", "xml"));*/
				if (mLastCurrentFolder != null) {
					fileChooser.setCurrentDirectory(mLastCurrentFolder);
				}
				int retVal = fileChooser.showOpenDialog(canvas);
				if (retVal == JFileChooser.APPROVE_OPTION) {
					String fileName = fileChooser.getSelectedFile()
							.getAbsolutePath();
					// Class <?> cls = fileRegister.findClassByExt(
					// Utils.getExtenstion( fileName) );
					canvas.createBioFile(fileName);
					mLastCurrentFolder = fileChooser.getCurrentDirectory();
					canvas.repaint();
				}
			}
		});
		JMenuItem saveMenuItem = new JMenuItem("Save project");
		saveMenuItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				saveProject("Save current project",false);
			}
		});
		menu.add(newMenuItem);
		menu.add(saveMenuItem);
		menu.add(loadMenuItem);
		menu.add(newFileMenuItem);
		menuBar.add(menu);
		add(menuBar, BorderLayout.NORTH);

		// menu.setSize(getWidth(), 20);
		canvas = new AppCanvas(this);
		canvas.project.clear();
		canvas.setSize(CANVAS_WIDTH, CANVAS_HEIGHT);
		// canvas.setLocation(0, CANVAS_OFFSET_Y);

		commandsCanvas = new CommandsListCanvas(canvas);
		commandsCanvas.setSize(200, CANVAS_HEIGHT);

		fileCanvas = new FileListCanvas(canvas);
		fileCanvas.setSize(200, CANVAS_HEIGHT);
		// commandsCanvas.setLocation(500, CANVAS_OFFSET_Y);

		JTabbedPane tabs = new JTabbedPane();

		tabs.addTab("Commands", commandsCanvas);
		tabs.addTab("Files", fileCanvas);

		JButton run = new JButton("                   RUN                    ");
		run.setPreferredSize(new Dimension(10, 50));
		// run.setComponentPopupMenu(popup)


		
		JPanel eastPanel = new JPanel();
		run.setAlignmentX(eastPanel.CENTER_ALIGNMENT);
		run.addActionListener(new buttonClickListener());

		eastPanel.setLayout(new BoxLayout(eastPanel, BoxLayout.PAGE_AXIS));
		eastPanel.add(tabs);
		eastPanel.add(run);

		add(textArea, BorderLayout.SOUTH);
		add(eastPanel, BorderLayout.EAST);

		add(canvas, BorderLayout.CENTER);

		validate();
		addKeyListener(canvas);

		// drag drop
		fileCanvas.getJlist().setDragEnabled(true);
		commandsCanvas.getJlist().setDragEnabled(true);
		DropTarget dt = new DropTarget(canvas, this);

		//addFocusListener(new FAdapter());
		addWindowFocusListener( new WindowFocusListener()
		{
			
			@Override
			public void windowLostFocus(WindowEvent e)
			{
				System.out.println("Focus lost");
			}
			
			@Override
			public void windowGainedFocus(WindowEvent e)
			{
				 System.out.println("started");
				 if ( canvas != null && canvas.project != null)
				 {
					 canvas.project.CheckFileDates(); 
						
				 }
			}
		} );
	}

	public void saveProject(String title,boolean clear) {
		JFileChooser fileChooser = new JFileChooser();
		fileChooser.setDialogTitle(title);
		fileChooser.setFileFilter(new FileNameExtensionFilter("XML", "xml"));
		if (mLastCurrentFolder != null) {

			fileChooser.setCurrentDirectory(mLastCurrentFolder);
		}
		if (fileChooser.showSaveDialog(canvas) == JFileChooser.APPROVE_OPTION) {
			String XMLfileName = fileChooser.getSelectedFile()
					.getAbsolutePath();
			if (XMLfileName.toLowerCase().indexOf(".xml") == -1) {
				XMLfileName += ".xml";
			}
			if (clear)
			{
				canvas.project.clear();
			}
			canvas.project.SaveToXML(XMLfileName);
			mProjectOpened = true;
			mLastCurrentFolder = fileChooser.getCurrentDirectory();
			canvas.repaint();
			PrintToLog("Project saved");
		};
	}

	public static void main(String[] args) {
		new Biolean();
	}

	public static void PrintToLog(String message) {
		textArea.Append(message);
	}

	@Override
	public void dragEnter(DropTargetDragEvent arg0) {

	}

	@Override
	public void dragExit(DropTargetEvent arg0) {

	}

	@Override
	public void dragOver(DropTargetDragEvent arg0) {

	}

	@Override
	public void drop(DropTargetDropEvent event) {

		try {			
			java.awt.datatransfer.Transferable tr = event.getTransferable();

			if (tr.isDataFlavorSupported(java.awt.datatransfer.DataFlavor.javaFileListFlavor)) {
				event.acceptDrop(java.awt.dnd.DnDConstants.ACTION_COPY);
				java.util.List fileList = (java.util.List) tr
						.getTransferData(java.awt.datatransfer.DataFlavor.javaFileListFlavor);
				java.util.Iterator iterator = fileList.iterator();
				java.io.File[] filesTemp = new java.io.File[fileList.size()];
				fileList.toArray(filesTemp);
				final java.io.File[] files = filesTemp;
				canvas.isDragExternalFile = true;
				canvas.dragExternalFile = files[0].toString();
				String fileName = files[0].getName();
				canvas.dragFile = canvas.createBioFile(fileName);
			} 
			else {				
				if (tr.isDataFlavorSupported(DataFlavor.stringFlavor)) {
					event.acceptDrop(DnDConstants.ACTION_MOVE);
					String s = (String) tr
							.getTransferData(DataFlavor.stringFlavor);
					if (s.equals(commandsCanvas.getJlist().getSelectedValue())) {
						int index = commandsCanvas.getJlist().getSelectedIndex();
						Class<?> instanceClass = Biolean.cmdRegister.getCommandClass(index);
						String cmdName = Biolean.cmdRegister.getName(index);
						commandsCanvas.getAppanel().addNewCommand(
								instanceClass, cmdName, event.getLocation());
					} else if (s.equals(fileCanvas.getJlist().getSelectedValue())) {
						int index = fileCanvas.getJlist().getSelectedIndex();
						Class<?> instanceClass = Biolean.fileRegister.getBioFileClass(index);
						String name = Biolean.fileRegister.getTypeName(index);
						fileCanvas.getAppanel().AddEmptyFile(instanceClass, name, event.getLocation());
					}
					event.getDropTargetContext().dropComplete(true);
				} else {
					event.rejectDrop();
				}
			}
		} catch (Exception exception) {
			System.err.println("Exception" + exception.getMessage());
			// event.rejectDrop();
		}

	}

	@Override
	public void dropActionChanged(DropTargetDragEvent arg0) {
	}

	public class buttonClickListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent arg0) {
			if (mProjectOpened) {
				canvas.project.execute();
			} else {
				PrintToLog("Create, save or load some project first");
				saveProject("Create new project",false);
			}
			biolean.requestFocus();
		}
	}
	
}
